home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-19
/
rk_plot.zip
/
PLOT.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1991-05-13
|
26KB
|
632 lines
{
┌───────────────────────────────────────────────────────────────────────────┐
│ │
│ Algorithmen zur grafischen Darstellung einer Funktion z = F(x,y). │
│ │
│ Version 1.0 │
│ │
├───────────────────────────────────────────────────────────────────────────┤
│ Copyright (C) 1991, Hans-Jürgen Herrler und Dieter Sosna │
└───────────────────────────────────────────────────────────────────────────┘
}
{ Soll in der Routine AlphaPunktSetzen geprüft werden, ob 0 <= x <= GetMaxX
und 0 <= y <= GetMaxY ist, muß die folgende Compilerdirektive entfernt
werden: }
{$DEFINE ALPHA-}
{$A+,F+,R-,S-}
UNIT Plot;
INTERFACE
USES Graph;
CONST
{ Maximalzahl von Gitterlinien in x- bzw. y-Richtung: }
MaxGitter = 100;
TYPE
Float = {$IFOPT N+} Single; { falls 80x87 vorhanden ist;
es ist auch Double möglich}
{$ELSE} Real;
{$ENDIF}
FloatPointer = ^Float;
{ Beschreibung der Matrix, die die Werte der darzustellenden Funktion
enthält: }
MatrixParameter = Record
XGitter, { Zahl der Gitterlinien bzw. Stützstellen }
YGitter : Word; { der Funktion in X- bzw. Y-Richtung, die
Zählung beginnt jeweils bei 1! }
ZMin, ZMax : Float { kleinster und größter Funktionswert }
END;
Projektionsart = (ZentralProjektion, ParallelProjektion);
{ Beschreibung des erzeugten Bildes: }
BildParameter = Record
SchirmLinks, { Bildschirm-Ausschnitt, in dem die }
SchirmRechts, { Darstellung erfolgt. Angegeben als }
SchirmOben, { als Bruchteil von GetMaxX, GetMaxY }
SchirmUnten : Float;
{ Farben: }
ColorLine, { Linienfarbe }
ColorFrame, { Bildrahmen }
{ Folgende Farben nur für Volumenperspektive: }
ColorFillO, { Füllfarbe Oberseite }
ColorFillU, { Füllfarbe Unterseite }
ColorFillX, { Füllfarbe Seitenflächen parallel X}
ColorFillY : Byte; { Füllfarbe Seitenflächen parallel Y}
Alpha, { horizontaler Betrachtungswinkel }
Gamma : Integer; { vertikaler Betrachtungswinkel }
Case
Projekt : Projektionsart {hier gewünschte Projektion angeben }
Of
ZentralProjektion:
(Abstand, { Betrachtungsabstand }
Brennweite : Word); { Brennweite }
ParallelProjektion:
(BrennweiteZuAbstand: Float) { Beeinflußt Größe bei Parallel-
projektion }
END;
{ ------------------------------------------------------------------------- }
PROCEDURE VolumenPerspektive(VAR Matrix; MatrixParm: MatrixParameter;
BildParm: BildParameter; UseHeap: Boolean);
PROCEDURE AlphaScheibenPerspektive(VAR Matrix; MatrixParm: MatrixParameter;
BildParm: BildParameter);
PROCEDURE GitterFlaechenPerspektive(VAR Matrix; MatrixParm: MatrixParameter;
BildParm: BildParameter; UseHeap: Boolean);
FUNCTION Element(P: Pointer; i, j, SpaltenLen: Word): FloatPointer;
{ Liefert Zeiger auf das Matrixelement(i, j) zurück. }
{ ========================================================================= }
IMPLEMENTATION
TYPE
GitterPktRec = Record
XNr, YNr: Word; { Indizes des Gitterpunktes }
ZPtr : FloatPointer; { Zeiger auf Z-Wert }
END;
{ Konstanten für die Transformation in Gerätekoordinaten und zur
Bilderzeugung: }
TransformationsParameter = Record
D1, D2, D3, D4, D5, { Transformationskonstanten, }
D6, D7, D8, { beschreiben die resultierende }
T1, T2, T3, { Matrix aller Transformationen }
GTX, GTY : Float;
ZSockel : Float;
iKrit, jKrit : Integer; { "kritische" Gitterlinien, abhängig
von der Lage des Augpunktes }
VonUntenSichtbar : Boolean;
Richtung : 'X'..'Y'; { Richtung bei Scheibenperspektive }
XGitter,
YGitter : Word;
Case
Projekt : Projektionsart Of
ParallelProjektion:
(BrennweiteZuAbstand: Float) { Beeinflußt Größe bei Parallel-
projektion }
END;
TempArray = Array[1..MaxGitter*MaxGitter] Of PointType;
TempArrayPtr= ^TempArray;
VAR
TrfParm : TransformationsParameter;
SizeOfFloat : Word;
{ ------------------------------------------------------------------------- }
FUNCTION Minimum(a, b: Integer): Integer;
BEGIN
IF a < b THEN Minimum := a ELSE Minimum := b
END;
{ ------------------------------------------------------------------------- }
FUNCTION Maximum(a, b: Integer): Integer;
BEGIN
IF a > b THEN Maximum := a ELSE Maximum := b
END;
{ ------------------------------------------------------------------------- }
{$L ZEIGER.OBJ}
FUNCTION Element(P: Pointer; i, j, SpaltenLen: Word): FloatPointer;
External;
{ Liefert Zeiger auf das Matrixelement(i, j) zurück. }
{ ------------------------------------------------------------------------- }
PROCEDURE IncPtr(Var P: FloatPointer);
External;
{ Rückt den bereits normalisierten(!) Zeiger auf das folgende Matrixelement.}
{ ------------------------------------------------------------------------- }
PROCEDURE Transformation(MatrixParm: MatrixParameter;
BildParm: BildParameter);
{ Berechnet Transformationskonstanten entsprechend der gewünschten
Darstellung. Aufruf darf erst nach InitGraph erfolgen! }
CONST
{ Folgende Konstanten charakterisieren die Transformation der Funktion:
Abzubildender Quader in Weltkoordinaten (Funktion nach der Skalierung) }
XWMin = -100; XWMax = +100;
YWMin = -100; YWMax = +100;
ZWMin = -50; ZWMax = +50;
{ Fenster in Weltkoordinaten ("Mattscheibe" in der Fotografie) }
UMin = -18; UMax = +18;
VMin = -12; VMax = +12;
Sockel = 0.2; { Sockelhöhe als Bruchteil von ZMax-ZMin }
VAR
AlphaBogen, GammaBogen, { Betrachtungswinkel im Bogenmaß }
SA, SG, CA, CG, { Sinus und Cosinus von Alpha bzw Gamma }
SFX, STX, SFY, STY, { Konstanten der Skalierungs-Transformation }
SFZ, STZ,
GFX, GFY : Float; { Konstanten der Geräte-Transformation }
{ Zur Bezeichnung:
S = Skalierungs-Transformation: reale Funktion -> Weltkoordinaten
G = Geräte-Transformation:
Fenster in Weltkoord. -> Ausschnitt in Gerätekoordinaten
F = Faktor T = Translation }
SchirmL, SchirmR, { Bildschirm-Ausschnitt in }
SchirmO, SchirmU : Integer; { Geräte-Koordinaten }
AX, AY : Float; { Weltkoordinaten des Augpunktes }
a, b : Float; { Hilfsvariable }
Sektor : 0..7; { zur Klassifikation von Alpha }
BEGIN
WITH TrfParm DO BEGIN
Projekt := BildParm.Projekt;
IF Projekt = ParallelProjektion THEN
BrennweiteZuAbstand := BildParm.BrennweiteZuAbstand;
XGitter := MatrixParm.XGitter;
YGitter := MatrixParm.YGitter;
{ ViewPort festlegen, Rahmen zeichnen }
WITH BildParm DO BEGIN
SchirmL := Round(GetMaxX * SchirmLinks);
SchirmR := Round(GetMaxX * SchirmRechts);
SchirmO := Round(GetMaxY * SchirmOben);
SchirmU := Round(GetMaxY * SchirmUnten);
SetColor(ColorFrame);
Rectangle(SchirmL, SchirmO, SchirmR, SchirmU);
SetViewPort(Succ(SchirmL), Succ(SchirmO),
Pred(SchirmR), Pred(SchirmU), ClipOn);
{ Berechnung von Transformationskonstanten }
AlphaBogen := Alpha * Pi / 180; GammaBogen := Gamma * Pi/ 180;
SA := Sin(AlphaBogen); SG := Sin(GammaBogen);
CA := Cos(AlphaBogen); CG := Cos(GammaBogen);
END;
WITH MatrixParm DO BEGIN
IF ZMax = ZMin THEN ZMax := Abs(ZMin) * 2 + 1;
ZSockel := ZMin - (ZMax - ZMin) * Sockel;
SFX := (XWMax - XWMin)/Pred(XGitter); STX := XWMin - SFX;
SFY := (YWMax - YWMin)/Pred(YGitter); STY := YWMin - SFY;
SFZ := (ZWMax - ZWMin)/(ZMax-ZSockel); STZ := ZWMin - SFZ * ZSockel
END;
GFX := (SchirmR - SchirmL)/(UMax - UMin);
GTX := - GFX * UMin;
GFY := (SchirmO - SchirmU)/(VMax - VMin);
GTY := SchirmU - GFY * VMin - SchirmO;
{ Eigentlich: GTX := SchirmL - GFX * UMin
GTY := SchirmU - GFY * VMin ,
durch das eingestellte Grafikfenster ergeben sich aber Verschiebungen! }
D1 := GFX * SFX * CA; D2 := GFX * SFY * SA;
D3 := -GFY * SFX * SA * SG; D4 := GFY * SFY * CA * SG;
D5 := GFY * SFZ * CG;
T1 := GFX *(STX * CA + STY * SA);
T2 := GFY *(-STX * SA * SG + STY * CA * SG + STZ * CG);
WITH BildParm DO IF Projekt = ZentralProjektion THEN BEGIN
D6 := -SFX * SA * CG / Brennweite;
D7 := SFY * CA * CG / Brennweite;
D8 := -SFZ * SG / Brennweite;
T3 := (-STX * SA * CG + STY * CA * CG - STZ * SG + Abstand)/Brennweite
END;
{ Richtung der Projektionsstrahlen bzw. Lage des Auges: }
WITH BildParm DO IF Projekt = ParallelProjektion THEN BEGIN
Sektor := ((Alpha + 180) Div 45) Mod 8;
CASE Sektor OF
0,1,2,3 : jKrit := -1;
4,5,6,7 : jKrit := XGitter+2
END;
CASE Sektor OF
2,3,4,5 : iKrit := -1;
0,1,6,7 : iKrit := YGitter+2
END;
CASE Sektor OF { Vorzugsrichtung bei ScheibenPerspektive }
0,3,4,7 : Richtung := 'X';
1,2,5,6 : Richtung := 'Y'
END;
IF Gamma < 0 THEN VonUntenSichtbar := True
ELSE VonUntenSichtbar := False;
END
ELSE BEGIN { ZentralProjektion }
AX := Abstand * CG * SA; AY := - Abstand * CG * CA;
a := (XGitter - 1) / (XWMax - XWMin);
b := 1 - a * XWMin;
jKrit := Trunc(a * AX + b);
a := (YGitter - 1) / (YWMax - YWMin);
b := 1 - a * YWMin;
iKrit := Trunc(a * AY + b);
IF Abstand * SG < ZWMin THEN VonUntenSichtbar := True
ELSE VonUntenSichtbar := False
END
END
END; { Transformation }
{ ------------------------------------------------------------------------- }
PROCEDURE Projektion(RaumPkt: GitterPktRec; Var BildPkt: PointType);
{ Transformation in Gerätekoordinaten }
VAR
FT : Float;
BEGIN
WITH TrfParm DO WITH RaumPkt DO BEGIN
IF Projekt = ZentralProjektion THEN
FT := 1 / (D6 * XNr + D7 * YNr + D8 * ZPtr^ + T3)
ELSE { ParallelProjektion }
FT := BrennweiteZuAbstand;
BildPkt.X := Round((D1 * XNr + D2 * YNr + T1)* FT + GTX);
BildPkt.Y := Round((D3 * XNr + D4 * YNr + D5 * ZPtr^ + T2)* FT + GTY)
END
END; { Projektion }
{ ------------------------------------------------------------------------- }
FUNCTION VorabProjektion(VAR Matrix; VAR TrfMatrix: TempArrayPtr): Boolean;
{ Projiziert die gesamte Matrix vorab auf Gerätekoordinaten, falls temporär
genug Platz auf dem Heap vorhanden ist. }
VAR
Size : LongInt;
i, j : Word;
GP : GitterPktRec;
BEGIN
WITH TrfParm DO BEGIN
Size := XGitter * YGitter * SizeOf(PointType);
IF MaxAvail >= Size THEN BEGIN
VorabProjektion := True;
GetMem(TrfMatrix, Size);
WITH GP DO FOR i := 1 TO YGitter DO BEGIN
YNr := i;
XNr := 1;
ZPtr := Element(@Matrix, YNr, XNr, XGitter);
Projektion(GP, TempArray(TrfMatrix^)[Pred(i)*XGitter+1]);
FOR j := 2 TO XGitter DO BEGIN
Inc(XNr);
IncPtr(ZPtr);
Projektion(GP, TempArray(TrfMatrix^)[Pred(i)*XGitter+j])
END
END
END
ELSE VorabProjektion := False
END
END;
{ ======= VolumenPerspektive ============================================== }
PROCEDURE VolumenPerspektive(VAR Matrix; MatrixParm: MatrixParameter;
BildParm: BildParameter; UseHeap: Boolean);
VAR
Vorab : Boolean;
TrfMatrix : TempArrayPtr;
{ ......................................................................... }
PROCEDURE Prisma(i, j: Integer);
{ Zeichnet Prisma unter Berücksichtigung der Sichtbarkeit }
TYPE
EckpunktNr = 1..8; { 8 Eckpunkte eines Prismas werden nummeriert }
FlaechenType = Array[1..4] of EckpunktNr;
CONST
{ Charakterisieren jedes Eckpunktes des Prismas. }
Index : Array[EckpunktNr,1..2] of Byte =
((0, 0), (1, 0), (1, 1), (0, 1),
(0, 0), (1, 0), (1, 1), (0, 1));
{ Charakterisieren der 6 Flächen des Prismas durch ihre Eckpunktnummern: }
Oben : FlaechenType = (5, 6, 7, 8);
Unten : FlaechenType = (1, 2, 3, 4);
LinksX : FlaechenType = (1, 4, 8, 5);
RechtsX : FlaechenType = (2, 3, 7, 6);
LinksY : FlaechenType = (1, 2, 6, 5);
RechtsY : FlaechenType = (4, 3, 7, 8);
{ ......................................................................... }
PROCEDURE Viereck(Flaeche: FlaechenType);
{ Angegebene Fläche zeichnen (Inneres dabei löschen) }
VAR
k : 1..4;
Ecke : EckPunktNr;
GP : GitterPktRec;
Polygon : Array[1..4] Of PointType;
BEGIN
WITH GP DO FOR k := 1 TO 4 DO BEGIN
Ecke := Flaeche[k];
XNr := j + Index[Ecke, 1];
YNr := i + Index[Ecke, 2];
IF Ecke < 5 THEN ZPtr := @TrfParm.ZSockel
ELSE ZPtr := Element(@Matrix, YNr, XNr, TrfParm.XGitter);
Projektion(GP, Polygon[k])
END;
FillPoly(4, Polygon)
END; { Viereck }
{ ......................................................................... }
PROCEDURE ViereckOben;
{ Entspricht dem Prozeduraufruf Viereck(Oben), ist aber optimiert! }
VAR
GP : GitterPktRec;
Polygon : Array[1..4] Of PointType;
BEGIN
IF Vorab THEN WITH TrfParm DO BEGIN
Polygon[1] := TempArray(TrfMatrix^)[Pred(i)*XGitter + j];
Polygon[2] := TempArray(TrfMatrix^)[Pred(i)*XGitter + Succ(j)];
Polygon[3] := TempArray(TrfMatrix^)[i*XGitter + Succ(j)];
Polygon[4] := TempArray(TrfMatrix^)[i*XGitter + j]
END
ELSE WITH GP DO BEGIN
XNr := j; YNr := i;
ZPtr := Element(@Matrix, YNr, XNr, TrfParm.XGitter);
Projektion(GP, Polygon[1]);
Inc(XNr);
IncPtr(ZPtr);
Projektion(GP, Polygon[2]);
Dec(XNr); Inc(YNr);
ZPtr := Element(@Matrix, YNr, XNr, TrfParm.XGitter);
Projektion(GP, Polygon[4]);
Inc(XNr);
IncPtr(ZPtr);
Projektion(GP, Polygon[3])
END;
FillPoly(4, Polygon)
END; { ViereckOben }
{ ......................................................................... }
BEGIN { Prisma }
SetFillStyle(SolidFill, BildParm.ColorFillO);
ViereckOben;
WITH TrfParm DO BEGIN
{ Nur wirklich sichtbare Seitenflächen zeichnen: }
IF (j=1) and (j>jKrit) THEN BEGIN
SetFillStyle(SolidFill, BildParm.ColorFillY);
Viereck(LinksX)
END;
IF (j=pred(XGitter)) and (j<jKrit) THEN BEGIN
SetFillStyle(SolidFill, BildParm.ColorFillY);
Viereck(RechtsX)
END;
IF (i=1) and (i>iKrit) THEN BEGIN
SetFillStyle(SolidFill, BildParm.ColorFillX);
Viereck(LinksY)
END;
IF (i=pred(YGitter)) and (i<iKrit) THEN BEGIN
SetFillStyle(SolidFill, BildParm.ColorFillX);
Viereck(RechtsY)
END;
IF VonUntenSichtbar THEN BEGIN
SetFillStyle(SolidFill, BildParm.ColorFillU);
Viereck(Unten)
END
END
END; { Prisma }
{ ......................................................................... }
VAR
i, j : Integer;
BEGIN { VolumenPerspektive }
Transformation(MatrixParm, BildParm);
Vorab := False;
IF UseHeap THEN Vorab := VorabProjektion(Matrix, TrfMatrix);
SetColor(BildParm.ColorLine);
WITH TrfParm DO BEGIN
FOR i := 1 TO Pred(Minimum(iKrit, YGitter)) DO
FOR j := 1 TO Pred(Minimum(jKrit, XGitter)) DO Prisma(i, j);
FOR j := Pred(XGitter) DOWNTO Maximum(jKrit, 1) DO
FOR i := 1 TO Pred(Minimum(iKrit, YGitter)) DO Prisma(i, j);
FOR j := 1 TO Pred(Minimum(jKrit, XGitter)) DO
FOR i := Pred(YGitter) DOWNTO Maximum(iKrit, 1) DO Prisma(i, j);
FOR i := Pred(YGitter) DOWNTO Maximum(iKrit, 1) DO
FOR j := Pred(XGitter) DOWNTO Maximum(jKrit, 1) DO Prisma(i, j);
IF Vorab THEN FreeMem(TrfMatrix, XGitter*YGitter*SizeOf(PointType))
END;
SetViewPort(0, 0, GetMaxX, GetMaxY, ClipOn)
END; { VolumenPerspektive }
{ ======= Modifizierter Alpha-Puffer-Algorithmus ========================== }
TYPE
PointArrayType = Array[1..MaxGitter+3] Of PointType;
VAR
maxTemp, minTemp,
AlphaMax, AlphaMin : Array[0..719] of Integer;
{ ausreichend für CGA, HGC, EGA }
AlphaColor : Byte;
{$IFDEF ALPHA-} {$L ALPHA-.OBJ}
{$ELSE} {$L ALPHA.OBJ}
{$ENDIF}
PROCEDURE AlphaLine(P1, P2: PointType); External;
{Zeichnet eine Linie von P1 nach P2 gemäß modifiziertem α-Puffer-Algorithmus}
PROCEDURE InitAlphaPuffer; External;
PROCEDURE AlphaPufferAktualisieren; External;
{ ------------------------------------------------------------------------- }
PROCEDURE AlphaPolyLine(NumPoints: Word; PolyPoints: PointArrayType);
VAR
i : Word;
BEGIN
FOR i := 1 TO Pred(NumPoints) DO
AlphaLine(PolyPoints[i], PolyPoints[Succ(i)])
END;
{ ======= AlphaScheibenPerspektive ======================================== }
VAR
Polygon : PointArrayType;
PROCEDURE AlphaScheibenPerspektive(VAR Matrix; MatrixParm: MatrixParameter;
BildParm: BildParameter);
{ ......................................................................... }
PROCEDURE AlphaScheibeX(i: integer); { eine Scheibe parallel X-Achse }
VAR
k : Word;
GP : GitterPktRec;
BEGIN
WITH GP DO BEGIN
XNr := 1;
YNr := i;
ZPtr := Element(@Matrix, YNr, XNr, TrfParm.XGitter);
Projektion(GP, Polygon[1]);
FOR k := 2 TO TrfParm.XGitter DO BEGIN
Inc(XNr);
IncPtr(ZPtr);
Projektion(GP, Polygon[k])
END;
ZPtr := @TrfParm.ZSockel;
Projektion(GP, Polygon[Succ(TrfParm.Xgitter)]);
XNr := 1;
Projektion(GP, Polygon[TrfParm.Xgitter+2]);
Polygon[TrfParm.XGitter+3] := Polygon[1];
END;
AlphaPolyLine(TrfParm.XGitter+3, Polygon);
AlphaPufferAktualisieren
END; { AlphaScheibeX }
{ ......................................................................... }
PROCEDURE AlphaScheibeY(j: integer); { eine Scheibe parallel Y-Achse }
VAR
k : Word;
GP : GitterPktRec;
BEGIN
WITH GP DO BEGIN
XNr := j;
YNr := 1;
ZPtr := Element(@Matrix, YNr, XNr, TrfParm.XGitter);
Projektion(GP, Polygon[1]);
FOR k := 2 TO TrfParm.YGitter DO BEGIN
Inc(YNr);
ZPtr := Element(@Matrix, YNr, XNr, TrfParm.XGitter);
Projektion(GP, Polygon[k])
END;
ZPtr := @TrfParm.ZSockel;
Projektion(GP, Polygon[Succ(TrfParm.Ygitter)]);
YNr := 1;
Projektion(GP, Polygon[TrfParm.Ygitter+2]);
Polygon[TrfParm.YGitter+3] := Polygon[1];
END;
AlphaPolyLine(TrfParm.YGitter+3, Polygon);
AlphaPufferAktualisieren
END; { AlphaScheibeY }
{ ......................................................................... }
VAR
i, j : Integer;
BEGIN { AlphaScheibenPerspektive }
Transformation(MatrixParm, BildParm);
InitAlphaPuffer;
AlphaColor := BildParm.ColorLine;
WITH TrfParm DO
IF Richtung = 'X' THEN BEGIN { Scheiben parallel X-Achse }
FOR i := Maximum(Succ(iKrit), 1) TO YGitter DO AlphaScheibeX(i);
FOR i := Minimum(iKrit, YGitter) DOWNTO 1 DO AlphaScheibeX(i)
END
ELSE BEGIN { Richtung = 'Y' , d.h. Scheiben parallel Y-Achse }
FOR j := Maximum(Succ(jKrit), 1) TO XGitter DO AlphaScheibeY(j);
FOR j := Minimum(jKrit, XGitter) DOWNTO 1 DO AlphaScheibeY(j)
END;
SetViewPort(0, 0, GetMaxX, GetMaxY, ClipOn)
END; { AlphaScheibenPerspektive }
{ ======= GitterFlächenPerspektive ======================================== }
PROCEDURE GitterFlaechenPerspektive(VAR Matrix; MatrixParm: MatrixParameter;
BildParm: BildParameter; UseHeap: Boolean);
VAR
Vorab : Boolean;
{ Wurde die ganze Matrix vorab auf Gerätekoordinaten transformiert? }
TrfMatrix : TempArrayPtr;
{ ......................................................................... }
PROCEDURE Feld(i, j: Integer); { Zeichnet ein Elementarfeld }
VAR
GP : GitterPktRec;
Polygon : Array[1..4] Of PointType;
BEGIN
IF Vorab THEN WITH TrfParm DO BEGIN
Polygon[1] := TempArray(TrfMatrix^)[Pred(i)*XGitter + j];
Polygon[2] := TempArray(TrfMatrix^)[Pred(i)*XGitter + Succ(j)];
Polygon[3] := TempArray(TrfMatrix^)[i*XGitter + Succ(j)];
Polygon[4] := TempArray(TrfMatrix^)[i*XGitter + j]
END
ELSE WITH GP DO BEGIN
XNr := j; YNr := i;
ZPtr := Element(@Matrix, YNr, XNr, TrfParm.XGitter);
Projektion(GP, Polygon[1]);
Inc(XNr);
IncPtr(ZPtr);
Projektion(GP, Polygon[2]);
Dec(XNr); Inc(YNr);
ZPtr := Element(@Matrix, YNr, XNr, TrfParm.XGitter);
Projektion(GP, Polygon[4]);
Inc(XNr);
IncPtr(ZPtr);
Projektion(GP, Polygon[3])
END;
WITH TrfParm DO BEGIN
IF (i <= iKrit) or (i = 1) THEN AlphaLine(Polygon[1], Polygon[2]);
IF (j >= jKrit) or (j = Pred(XGitter)) THEN
AlphaLine(Polygon[2], Polygon[3]);
IF (i >= iKrit) or (i = Pred(YGitter)) THEN
AlphaLine(Polygon[3], Polygon[4]);
IF (j <= jKrit) or (j = 1) THEN AlphaLine(Polygon[4], Polygon[1])
END;
AlphaPufferAktualisieren
END; { Feld }
{ ......................................................................... }
VAR
i, j : Integer;
BEGIN { GitterFlaechenPerspektive }
Transformation(MatrixParm, BildParm);
Vorab := False;
IF UseHeap THEN Vorab := VorabProjektion(Matrix, TrfMatrix);
AlphaColor := BildParm.ColorLine;
InitAlphaPuffer;
WITH TrfParm DO BEGIN
FOR i := Maximum(iKrit, 1) TO Pred(YGitter) DO
FOR j := Minimum(jKrit, Pred(XGitter)) DOWNTO 1 DO Feld(i, j);
FOR j := Maximum(succ(jKrit), 1) TO Pred(XGitter) DO
FOR i := Maximum(iKrit, 1) TO Pred(YGitter) DO Feld(i, j);
FOR i := Pred(Minimum(iKrit, YGitter)) DOWNTO 1 DO
FOR j := Maximum(jKrit, 1) TO Pred(XGitter) DO Feld(i, j);
FOR j := Pred(Minimum(jKrit, XGitter)) DOWNTO 1 DO
FOR i := Pred(Minimum(iKrit, YGitter)) DOWNTO 1 DO Feld(i, j);
IF Vorab THEN FreeMem(TrfMatrix, XGitter * YGitter * SizeOf(PointType))
END;
SetViewPort(0, 0, GetMaxX, GetMaxY, ClipOn)
END; { GitterFlaechenPerspektive }
{ ======= Initialisierungen =============================================== }
BEGIN
SizeOfFloat := SizeOf(Float)
END.